package com.nq.utils.task.tsanghi;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nq.common.SystemVersionEnum;
import com.nq.dao.*;
import com.nq.pojo.*;
import com.nq.service.IFundsApplyService;
import com.nq.service.IUserService;
import com.nq.stock.entity.StStockIntroduction;
import com.nq.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 配资的定时任务
 */
@Component
@Slf4j
public class FundsApplyComponent {

    @Resource
    private FundsApplyMapper fundsApplyMapper;
    @Resource
    private FundsLeverMapper fundsLeverMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserCashDetailMapper userCashDetailMapper;
    @Resource
    private IUserService userService;

    @Resource
    private StAllocationSettingMapper stAllocationSettingMapper;

    @Value("${spring.profiles.active}")
    private String active;

    /**
     * 凌晨1点 执行扣除配资管理费
     * 管理费只能从保证金中扣除，不可以在可用余额中扣除
     */
    // @PostConstruct
    @Scheduled(cron = "0 0 1 * * ?")
    public void doDeductionMargin() {
        log.info("执行定时任务: 执行扣除配资保证金 开始");

        // 印度版不需要扣管理费，需要过滤一下
        if (SystemVersionEnum.india.name().equals(active)) {
            return;
        }

        // 查询所有的已审核的配资记录
        List<FundsApply> list = fundsApplyMapper.queryHasAudited();
        for (FundsApply fundsApply : list) {
            // 查询对应的管理费率
            AtomicReference<StAllocationSetting> setting = new AtomicReference<>(new StAllocationSetting());
            List<StAllocationSetting> settingList = stAllocationSettingMapper.selectList(null);
            settingList.forEach(set -> {
                // 前开后闭
                if (fundsApply.getFundsAmount().compareTo(set.getLow()) > 0 && fundsApply.getFundsAmount().compareTo(set.getHigh()) <= 0) {
                    setting.set(set);
                }
            });
            if (null == setting) {
                return;
            }
            // 计算管理费率
            BigDecimal manageRate = setting.get().getRate();

            BigDecimal fundsAmount = fundsApply.getFundsAmount();

            // 计算需要扣除的管理费
            BigDecimal retePrice = fundsAmount.multiply(manageRate);

            // 增加管理费
            BigDecimal appendManageFee = fundsApply.getManageFee().add(retePrice);
            // 如果保证金大于总管理费，则继续追加管理费
            if (fundsApply.getMargin().compareTo(appendManageFee) >= 0) {

                Integer userId = fundsApply.getUserId();
                User user = userMapper.selectByPrimaryKey(userId);
                if (null == user) {
                    continue;
                }

                FundsApply updateApply = new FundsApply();
                updateApply.setId(fundsApply.getId());
                updateApply.setManageFee(appendManageFee);
                updateApply.setUpdateTime(new Date());
                // 更新配资信息的保证金
                fundsApplyMapper.update(updateApply);

                // 配资记录
                UserCashDetail details = new UserCashDetail();
                details.setPositionId(fundsApply.getId());
                details.setAgentId(user.getAgentId());
                details.setAgentName(user.getAgentName());
                details.setUserId(user.getId());
                details.setUserName(user.getRealName());
                details.setDeType("The management fee is deducted from the user allocation account");
                details.setDeAmt(retePrice);
                details.setDeSummary("Application for daily allocation:" + fundsApply.getOrderNumber() + "，" +
                        "The management fee is deducted from the user's allocation account, and the remaining available amount of the user's allocation account" + user.getTradingAmount());
                details.setAddTime(new Date());
                details.setIsRead(0);
                userCashDetailMapper.insert(details);

            }else {
                // 如果保证金小于总管理费，则直接修改状态为保证金不足
                fundsApply.setStatus(FundsApply.STATUS_6);
                fundsApplyMapper.update(fundsApply);
            }
        }
    }


    /**
     * 检测保证金不足超过3天的数据
     * 如果超过3天不补充保证金，则直接强制平仓
     */
    @Scheduled(cron = "0 10 1 * * ?")
    public void over3DaysNotEnoughForMargin() {
        log.info("开始执行保证金不足检测方法，{}", LocalDate.now());
        LocalDate today = LocalDate.now(); // 获取今天的日期
        LocalDate threeDaysAgo = today.minusDays(3); // 获取3天前的日期
        QueryWrapper<FundsApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", FundsApply.STATUS_6);
        queryWrapper.between("update_time", today, threeDaysAgo);
        List<FundsApply> fundsApplyList = fundsApplyMapper.selectList(queryWrapper);
        log.info("获取到 {} 条保证金不足的数据，fundsApplyList {}", fundsApplyList.size(), fundsApplyList);
        if (CollUtil.isNotEmpty(fundsApplyList)) {
            fundsApplyList.stream().forEach(fundsApply -> {
                User user = userMapper.selectById(fundsApply.getUserId());
                if (null == user) {
                    return;
                }
                // 强制平仓
                userService.handleClosePosition(user);
            });
        }

    }

}
